package cc.linker.steplink.crm.merchanth5.service;

import cc.linker.steplink.crm.commons.FeeConstants;
import cc.linker.steplink.crm.commons.TradeTypeConstants;
import cc.linker.steplink.crm.commons.constant.TlPayConstant;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.lock.LettuceLock;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.commons.utils.TransactionOrderUtil;
import cc.linker.steplink.crm.merchanth5.dao.DongGoodsDao;
import cc.linker.steplink.crm.merchanth5.dao.MaiBaoLaDao;
import cc.linker.steplink.crm.merchanth5.dao.MallDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.model.OrderAddressDto;
import cc.linker.steplink.crm.merchanth5.pojo.*;
import cc.linker.steplink.crm.merchanth5.pojo.acs.GoodsParamPo;
import cc.linker.steplink.crm.merchanth5.pojo.acs.TradeInfo;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessNewService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessService;
import cc.linker.steplink.crm.merchanth5.service.redis.GoodsService;
import cc.linker.steplink.crm.merchanth5.util.ParamSignUtils;
import cc.linker.steplink.crm.merchanth5.util.Timer.TimerContext;
import cc.linker.steplink.crm.merchanth5.util.Timer.TimerScheduler;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 懂小姐业务
 * @Author: wuhangfeng
 * @Date: Created in 2019/11/14 13:27
 * @Version: 1.11.6
 */
@Slf4j
@Service
public class DongGoodsService {

    @Autowired
    private MallDao mallDao;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private LettuceLock lettuceLock;
    @Autowired
    private MallService mallService;
    @Autowired
    private DongGoodsDao dongGoodsDao;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private MaiBaoLaDao maiBaoLaDao;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private MaiBaoLaService maiBaoLaService;
    @Autowired
    private PurchaseProcessService purchaseProcessService;
    @Autowired
    private PurchaseProcessNewService purchaseProcessNewService;
    @Autowired
    private DataSourceTransactionManager txManager;

    // 锁
    private static final String DONG_CREATE_ORDER_LOCK = "DONG:CREATE_ORDER_LOCK";
    // 分账信息
    private static final String DONG_CREATE_ORDER_INFO = "DONG:CREATE_ORDER_INFO";
    // 调用返回结果
    private static final String DONG_CREATE_ORDER_RESULT = "DONG:CREATE_ORDER_RESULT";
    // 调用通联参数
    private static final String DONG_CREATE_ORDER_TL_PARAM = "DONG:CREATE_ORDER_TL_PARAM";
    // 调用通联交易信息
    private static final String DONG_CREATE_ORDER_TL_TRADE= "DONG:CREATE_ORDER_TL_TRADE";

    //返润比例
    public static final String ORG_PAY_KEY = "orgPay:org_pay_";
    //抽成比例
    public static final String ORG_SET_INFO_KEY = "orgSet:org_set_";
    //商品详情
    public static final String ORDER_GOODS_INFO = "orderGoodsInfo:goodsId_";
    //sku对应的mallsSku
    public static final String ORDER_MALL_GOODS_SKUID = "orderMallGoodsSkuId:goodsId_";
    //商品价格
    public static final String ORDER_GOODS_PRICE = "orderGoodsPrice:goodsId_";

    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 创建订单
     */
    public Map createOrder(Map<String, Object> param) throws GlobalException {
        // 获取地址
        OrderAddressDto orderAddressDto = mallDao.getDefaultReceiveAddress(param);
        if (orderAddressDto == null) {
            throw GlobalException.build("地址不存在或用户与地址不匹配");
        }
        // 用户id
        String customerId = (String) param.get("customerId");
        // 机构id
        String orgId = (String) param.get("orgId");
        // 分享人id
        String distributor = (String) param.get("distributor");
        // 代理搭配师ID
        String designerId = (String) param.get("designerId");
        // 是否使用积分
        String scoreStr = param.get("score").toString();
        // 剩余积分
        Integer score = null;
        if ("1".equals(scoreStr)) {
            score = purchaseProcessDao.getScoreByCustomerId(customerId);
        }
        // 只针对用户上了锁，后期可以优化
        String lockKey = DONG_CREATE_ORDER_LOCK + customerId;
        String requestId = UUID.randomUUID().toString();
        // 加锁
        boolean lock = lettuceLock.tryLock(lockKey,requestId,2,TimeUnit.MINUTES);
        if (!lock) {
            throw GlobalException.build("请勿重复购买");
        }
        try {
            // 商品id
            String goodsId = (String) param.get("goodsId");
            // 购物车id
            String shoppingCartIds = (String) param.get("shoppingCartIds");
            // 订单sn
            String orderSn = (String) param.get("orderSn");
            // 订单总金额order、商品总金额goods，单位：分，若为小b商品则有goodsId
            Map<String, Object> totalFee;
            // 订单id的list(其实理论上只有一个)
            List<Long> orderIds = new ArrayList<>();
            // 是否为支付未支付订单
            boolean rePay = false;
            // 获取机构支付模式
            Integer payMode = mallService.getPayModeByOrgId(orgId);
            param.put("payMode", payMode);
            // 生成订单，统计商品价格、订单价格
            if (!StringUtils.isEmpty(goodsId)) {
                // 直接购买商品
                // 订单sn
                orderSn = TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey();
                param.put("orderSn", orderSn);
                // 生成订单
                totalFee = this.insertMerchantOrder(param, orderAddressDto, orderIds);
            } else if (!StringUtils.isEmpty(shoppingCartIds)) {
                totalFee = new HashMap<>();
                // TODO 购买购物车商品 暂时没有
                // 订单sn
                //orderSn = TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey();
                //param.put("orderSn", orderSn);
                // 生成订单
                //totalFee = this.insertMerchantOrderByShoppingCart(param, orderAddressDto, orderIds);
            } else if (!StringUtils.isEmpty(orderSn)) {
                // 支付未支付订单
                totalFee = new HashMap<>();
                rePay = true;
            } else {
                throw GlobalException.build("参数错误");
            }
            // 0元商品 暂时没有
            if (!rePay && 0 == Long.valueOf(totalFee.get("order").toString())) {
                this.zeroBuy(orderSn);
                Map<String, Object> map = new HashMap<>();
                map.put("status", -2);
                map.put("orderSn", orderSn);
                return map;
            }
            // 根据商品和订单价格，以及是否使用积分，计算出钱款流向，组装json后调网关
            // 支付未支付订单，去redis拿签名
            String res;
            if (rePay) {
                String s = stringRedisTemplate.opsForValue().get(DONG_CREATE_ORDER_RESULT + orderSn);
                if (!StringUtils.isEmpty(s)) {
                    // 已生成签名
                    res = s;
                }else {
                    if(payMode==2){
                        //重新获取参数
                        res = buyUnpayGoods(orderSn);
                    }else{
                        // 签名数据，先去redis看看有没有
                        throw GlobalException.build("订单已失效");
                    }
                }
            } else if (totalFee.containsKey("goodsId")) {
                System.out.println("==========small==========="+JSONObject.toJSONString(totalFee));
                // 直接购买小b商品，产生推荐费、服务费和平台费
                res = this.buyGoods(totalFee, orgId, orderSn, score, customerId, distributor,designerId,payMode,"smallB");
            } else {
                System.out.println("==========big==========="+JSONObject.toJSONString(totalFee));
                if(goodsId!=null){
                    totalFee.put("goodsId", Long.valueOf(goodsId));
                }
                // 购买商城货架商品，产生平台费 目前参与分润的商品
                res = this.buyGoods(totalFee, orgId, orderSn, score, customerId, distributor,designerId,payMode,"bigB");
            }
            // 调网关拿签名
            if (!rePay) {
                // 扣积分
                Long scoreUse = Long.valueOf(totalFee.get("score").toString());
                if(scoreUse!=null&&scoreUse!=0){
                    int i = purchaseProcessDao.updateScoreByCustomerId(scoreUse, customerId);
                    //插入懂小姐交易记录
                    Map<String, Object> dongTrade = new HashMap<>();
                    dongTrade.put("orgId", orgId);
                    dongTrade.put("payUser", customerId);
                    dongTrade.put("receiveUser", orgId);
                    dongTrade.put("amount", scoreUse);
                    dongTrade.put("type", 5);
                    dongTrade.put("payRole", 0);
                    dongTrade.put("receiveRole", 5);
                    dongGoodsDao.insertDongScoreTradeInfo(dongTrade);
                    if (i != 1) {
                        // 这个判断好像没用，没开UpdateAffectedRows，所以用户锁暂时不能改
                        throw GlobalException.build("积分扣除失败");
                    }
                }
                purchaseProcessDao.updateOrderScore(orderSn, scoreUse);
                // 定时关闭订单(超时恢复库存) + 恢复用户积分
                //this.closeOrderAtRegularIntervals(orgId,orderIds, scoreUse, customerId);
                // 删除购物车商品
                if (!StringUtils.isEmpty(shoppingCartIds)) {
                    String[] split = shoppingCartIds.split(",");
                    for (String shoppingCartId : split) {
                        mallDao.deleteShoppingCartById(Long.parseLong(shoppingCartId));
                    }
                }
            }
            if ("".equals(res)) {
                this.zeroBuy(orderSn);
                Map<String, Object> map = new HashMap<>();
                map.put("status", -2);
                map.put("orderSn", orderSn);
                return map;
            }
            Map result = (Map) JSON.parse(res);
            result.put("orderSn", orderSn);
            return result;
        } finally {
            // 解锁
            lettuceLock.releaseLock(lockKey,requestId);
        }
    }

    /**
     * 订单支付回调
     */
    public void payCallback(Map<String, Object> param) throws Exception {
        Integer type = purchaseProcessDao.checkOrderTypeByOrderSn(param);
        switch (type) {
            case 3:
                //提現
                //this.withdrawCallback(param);
                break;
            case 2:
                // 商品购买
                if ("20".equals(param.get("status").toString())) {
                    this.shopCallback(param);
                }
                break;
            case 1:
                // 开通联盟商家和加盟代理
                if ("20".equals(param.get("status"))) {
                    //this.joinCallback(param);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 直接购买生成订单
     */
    private Map<String, Object> insertMerchantOrder(Map<String, Object> map, OrderAddressDto orderAddressDto, List<Long> orderIds) throws GlobalException {
        // 商品数量
        Integer goodsNum = (Integer) map.get("goodsNum");
        // skuId
        String skuId = null;
        if(map.get("skuId")!=null){
            skuId = map.get("skuId").toString();
        }
        ShoppingCartGoodsPo goodsPo = goodsService.getGoodsSkuInfo(map);
        if(null == goodsPo){
            throw GlobalException.build("商品不存在或已下架");
        }
        if (goodsPo.getIsDelete() == 1 || goodsPo.getDongGoodsStatus() != 1) {
            throw GlobalException.build("商品不存在或已下架");
        }
        if (goodsPo.getGoodsCount() < goodsNum) {
            throw GlobalException.build("商品库存不足");
        }
        Integer quota = maiBaoLaService.quota(goodsPo.getGoodsId().toString(), (String) map.get("customerId"));
        if (quota == -3) {
            throw GlobalException.build("您不满足购买条件");
        }
        if (goodsNum > quota && quota != -1) {
            throw GlobalException.build(goodsPo.getGoodsName() + "商品超过了限购上限");
        }
        int updateCount;
        if (goodsPo.getSkuId() == null) {
            updateCount = purchaseProcessService.saveMallsGoodsCount(goodsPo.getGoodsId(), null, goodsNum, goodsPo.getMallsGoodsId(), goodsPo.getMallsSkuId());
        }else{
            updateCount = purchaseProcessService.saveMallsGoodsCount(goodsPo.getGoodsId(), goodsPo.getSkuId().toString(), goodsNum, goodsPo.getMallsGoodsId(), goodsPo.getMallsSkuId());
        }
        if (updateCount == 0) {
            throw GlobalException.build("商品库存不足");
        }
        //供货价
        Long mallsAmount = 0L;
        if (orderAddressDto == null) {
            orderAddressDto = new OrderAddressDto();
        }
        //运费模板
        Map<String, Object> goodsShippingFee = purchaseProcessService.getGoodsShippingFee(orderAddressDto.getAddressId().intValue(), goodsPo.getGoodsId().intValue(), goodsPo.getBuyCount());
        if ((Boolean) goodsShippingFee.get("sta")) {
            goodsPo.setGoodsFreightCent((Long) goodsShippingFee.get("fee"));
        } else {
            throw GlobalException.build(goodsShippingFee.get("tip").toString());
        }
        if(!StringUtils.isEmpty(goodsPo.getMallsGoodsId())){
            if(goodsPo.getSkuId() == null){
                mallsAmount = goodsPo.getMallsAmount();
            }else{
                mallsAmount = goodsPo.getSkuMallsAmount();
            }
        }
        // 商品总价
        long goodsAmountCent = goodsPo.getAmountCent() * goodsNum;
        map.put("goodsAmountCent", goodsAmountCent);
        // 订单总价
        long orderAmountCent = goodsAmountCent + goodsPo.getGoodsFreightCent();
        map.put("orderAmountCent", orderAmountCent);
        map.put("orderTotalPriceCent", orderAmountCent);
        map.put("goods", goodsPo);
        map.put("address", orderAddressDto);
        map.put("orderRebate", "1");
        map.put("orderGoodsType", 1);
        String belongId = goodsPo.getBelongId();
        String orgId = "";
        if(!StringUtils.isEmpty(map.get("orgId"))){
            orgId = map.get("orgId").toString();
        }
        map.put("belongId",StringUtils.isEmpty(belongId)?orgId:belongId);
        if(StringUtils.isEmpty(map.get("storeId"))){
            map.put("storeId",map.get("belongId"));
        }
        // goodsFreightCent areaName cityName provinceName addressInfo phone realName
        //事务管理
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = txManager.getTransaction(def);
        purchaseProcessDao.insertOrderByMap(map);
        orderIds.add((Long) map.get("orderId"));
        // amountCent goodsCover goodsName skuKey skuValue
        purchaseProcessDao.insertOrderGoodsByMap(map);
        if (null != goodsPo.getMallsGoodsId()) {
            String purchaseOrderSn = TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey();
            map.put("mallsGoodsId", goodsPo.getMallsGoodsId());
            map.put("recId", map.get("recId"));
            map.put("purchaseOrderSn", purchaseOrderSn);
            map.put("orderSn", map.get("orderSn"));
            map.put("mallsAmount", mallsAmount == null ? 0 : mallsAmount);
            Map mallsGoodsInfo = goodsService.getGoodsInfo(goodsPo.getMallsGoodsId().toString());
            map.put("goodsName", mallsGoodsInfo.get("goodsName"));
            map.put("goodsNum", goodsNum);
            map.put("goodsImage", mallsGoodsInfo.get("goodsCover"));
            map.put("shippingFee", goodsPo.getGoodsFreightCent());
            purchaseProcessDao.addPurchaseOrder(map);
        }
        txManager.commit(status);
        // 添加记录
        map.put("objectId", map.get("orderSn"));
        mallService.addToDealData(map, 3);
        Map<String, Object> fee = new HashMap<>();
        fee.put("goods", goodsAmountCent);
        fee.put("order", orderAmountCent);
        fee.put("recId", map.get("recId"));
        fee.put("skuId", skuId);
        fee.put("goodsNum", goodsNum);
        fee.put("shippingFee", goodsPo.getGoodsFreightCent());
        if (!StringUtils.isEmpty(goodsPo.getBelongId())) {
            // 如果为小b商品
            fee.put("goodsId", goodsPo.getGoodsId());
        }
        return fee;
    }

    /**
     * 定时关闭订单
     */
    private void closeOrderAtRegularIntervals(String orgId,List<Long> orderIds, Long scoreUse, String customerId) {
        TimerContext context = new TimerContext(3600, 1);
        TimerScheduler scheduler = new TimerScheduler(context);
        final List<Long> orderInfos = orderIds;
        scheduler.addTask(() -> {
            try {
                for (Long orderId : orderInfos) {
                    int result = mallDao.closeMerchantOrderInfo(orderId);
                    if (result > 0) {
                        List<MerchantOrderGoodsPo> goodsPoList = purchaseProcessDao.getOrderGoodsListByOrderId(orderId);
                        for (MerchantOrderGoodsPo goods : goodsPoList) {
                            Map<String, Object> params = new HashMap<>();
                            //恢复库存
                            params.put("goodsId", goods.getGoodsId());
                            params.put("skuKey", goods.getSkuKey());
                            params.put("goodsNum", goods.getBuyCount());
                            if (goods.getSkuKey() == null) {//未设置SKU
                                int ifSku = mallDao.getIfGoodsSetSku(params);
                                if (ifSku == 0) {
                                    mallDao.addGoodsCount(params);
                                }
                            } else {//设置
                                int rt = mallDao.addGoodsSkuCount(params);
                                if (rt > 0) {
                                    mallDao.addGoodsCount(params);
                                }
                            }
                        }
                    }
                }
                // 恢复积分
                if (scoreUse!=null&&scoreUse > 0) {
                    purchaseProcessDao.addScoreByCustomerId(scoreUse, customerId);
                    //插入懂小姐交易记录
                    Map<String, Object> dongTrade = new HashMap<>();
                    dongTrade.put("orgId", orgId);
                    dongTrade.put("payUser", orgId);
                    dongTrade.put("receiveUser", customerId);
                    dongTrade.put("amount", scoreUse);
                    //退回
                    dongTrade.put("type", 6);
                    dongTrade.put("payRole", 5);
                    dongTrade.put("receiveRole", 0);
                    dongGoodsDao.insertDongScoreTradeInfo(dongTrade);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 3600);
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(scheduler, 0, context.getTickDuration() * 1000L);
    }

    /**
     * 购买商品
     * score 暂时不做
     */
    private String buyGoods(Map<String, Object> totalFee, String orgId, String orderSn, Integer score,
                            String customerId, String distributor,String designerId,Integer payMode,String useType) throws GlobalException {
        //订单价格
        Long orderAmount = Long.valueOf(totalFee.get("order").toString());
        // 商品描述
        String goodsName = purchaseProcessDao.getGoodsNameByGoodsId(totalFee.get("goodsId").toString());
        // 调用支付网关
        // 支付用户OPENID
        String openId = purchaseProcessDao.getMissOpenIdByCustomerId(customerId);
        //获取交易信息
        DongCommissionTradeInfoPo tradeInfoPo = getCommissionTradeInfo(totalFee,orgId,customerId,distributor,designerId,useType,score,orderSn,payMode,goodsName);
        List<Map<String, Object>> tradeInfos = tradeInfoPo.getCommissionTradeInfo();
        if(payMode==2){
            // 请求h5用户开户
            Map<String, Object> map = new HashMap<>();
            map.put("customerId", customerId);
            map.put("openId",openId);
            map.put("orgId", orgId);
            checkCustomerAccount(map);
        }
        // 请求参数
        String result = "";
        if(payMode==1){
            //微信支付
            // 请求支付网关
            Map<String, Object> req = this.getWxPayParam(openId, orderSn, String.valueOf(orderAmount), orgId);
            try {
                Long pay = Long.valueOf(totalFee.get("pay").toString());
                if (pay != 0L) {
                    result = httpService.doPost(wcPayProperties.getPayurl() + "/pay/wcpay", req);
                    result = this.callResultProcessWx(result);
                }
            } catch (Exception e) {
                throw GlobalException.build("支付网关调用异常");
            }
        }else if(payMode==2){
            //通联支付
            // 请求参数
            // 小b和大b要去查uid
            String notifyUrl = systemProperties.getScrmUrl() + "dong/paycallback";
            String orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
            Map<String, Object> reqMap = new HashMap<>();
            // 现金支付金额
            reqMap.put("cashAmount", totalFee.get("order"));
            List<Map<String, Object>> cashSplitItems = tradeInfoPo.getCashSplitItems();
            // 现金分账明细，JSON字符串
            if (cashSplitItems.size() > 0) {
                reqMap.put("cashSplitItems", JSON.toJSONString(cashSplitItems));
            }
            // 收款人id 收款人银行账号 金额 备注 订单sn
            // 支付用户ID
            reqMap.put("customerId", customerId);
            reqMap.put("goodsName", goodsName);
            // 支付用户OPENID
            reqMap.put("openID", openId);
            // 平台订单ID
            reqMap.put("orderSn", orderSn);
            // 收款用户ID
            reqMap.put("payeeUserID", orgUid);
            // 应用appId
            String appId = "wx2303ee6d7356a7c5";//purchaseProcessDao.getAppIdByOrgId(orgId);
            if (StringUtils.isEmpty(appId)) {
                throw GlobalException.build("appId获取失败");
            }
            reqMap.put("appId", appId);
            // 行业代码
            String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
            reqMap.put("industryCode", industryCode);
            // 行业名称
            String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode);
            reqMap.put("industryName", industryName);
            // 支付方式：WX-公众号支付；XCX-微信小程序支付
            reqMap.put("payType", "XCX");
            // 访问终端类型:1手机；2PC
            reqMap.put("source", 1);
            // 交易验证方式：0-无验证；1-短信验证码；2-支付密码
            reqMap.put("validateType", 0);
            // 测试环境用yt
            String alias = getAlias(orgId);
            reqMap.put("clintType", alias);
            reqMap.put("notifyUrl", notifyUrl);
            // 手续费
            reqMap.put("fee", 0);
            // 调用通联参数
            stringRedisTemplate.opsForValue().set(DONG_CREATE_ORDER_TL_PARAM + orderSn, JSON.toJSONString(reqMap), 60, TimeUnit.MINUTES);
            // 调用通联交易信息
            stringRedisTemplate.opsForValue().set(DONG_CREATE_ORDER_TL_TRADE + orderSn, JSON.toJSONString(tradeInfoPo), 60, TimeUnit.MINUTES);
            String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_PAY_ORDER;
            // 请求支付网关
            try {
                result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
                result = callResultProcessTL(result);
                // 保存请求信息和当前平台费比例
                Map<String, String> platformRateMap = tradeInfoPo.getPlatformRateMap();
                //联汇抽成
                Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
                //大b抽成
                Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));
                purchaseProcessDao.saveTlPayReqParam(orderSn, JSON.toJSONString(reqMap), linkerTake.toString(), unionBarleyTake.toString());
            } catch (Exception e) {
                throw GlobalException.build("支付网关调用异常");
            }
        }
        // 分账数据
        stringRedisTemplate.opsForValue().set(DONG_CREATE_ORDER_INFO + orderSn, JSON.toJSONString(tradeInfos), 60, TimeUnit.MINUTES);
        // 签名数据
        stringRedisTemplate.opsForValue().set(DONG_CREATE_ORDER_RESULT + orderSn, result, 60, TimeUnit.MINUTES);
        return result;
    }

    private String buyUnpayGoods(String orderSn) throws GlobalException {
        // 调用通联参数
        String params = stringRedisTemplate.opsForValue().get(DONG_CREATE_ORDER_TL_PARAM + orderSn);
        if(StringUtils.isEmpty(params)){
            throw GlobalException.build("订单已失效");
        }
        String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_PAY_ORDER;
        String result = "";
        // 请求支付网关
        try {
            result = httpService.doPost(url, params, WcPayConstant.JSON);
            result = callResultProcessTL(result);
            String tradeInfoPoStr = stringRedisTemplate.opsForValue().get(DONG_CREATE_ORDER_TL_TRADE + orderSn);
            DongCommissionTradeInfoPo tradeInfoPo = JSONObject.parseObject(tradeInfoPoStr,DongCommissionTradeInfoPo.class);
            // 保存请求信息和当前平台费比例
            Map<String, String> platformRateMap = tradeInfoPo.getPlatformRateMap();
            //联汇抽成
            Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
            //大b抽成
            Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));
            purchaseProcessDao.saveTlPayReqParam(orderSn, result, linkerTake.toString(), unionBarleyTake.toString());
        } catch (Exception e) {
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }

    private DongCommissionTradeInfoPo getCommissionTradeInfo(Map<String, Object> totalFee,String orgId,String customerId,
                                                             String distributor,String designerId,String userType,Integer score,
                                                             String orderSn,Integer payMode,String goodsName){
        System.out.println("====================="+userType);
        DongCommissionTradeInfoPo tradeInfoPo = new DongCommissionTradeInfoPo();
        //系统内交易信息
        List<Map<String, Object>> tradeInfos =  new ArrayList<>();
        //通联分账信息
        List<Map<String, Object>> cashSplitItems = new ArrayList<>();
        String dsIdentity = dongGoodsDao.getUserIdentity(designerId);
        //如果TA秀绑定的搭配师身份已经失效，不分润
        if(!("2").equals(dsIdentity)){
            designerId = null;
        }
        //获取用户锁定导购
        String sgId = dongGoodsDao.getBindSgId(customerId);
        //如果商品分享则身份为普通用户，则获得返润为积分
        String distributorId = dongGoodsDao.getUserIdentity(distributor);
        boolean serviceScore = false;
        if(("0").equals(distributorId)){
            serviceScore = true;
        }else if(("1").equals(distributorId)||("2").equals(distributorId)){
            //分享人是导购或者搭配师时，如果购买用户没有锁定导购，则锁定
            if(sgId==null){
                Map<String,Object> params = new HashMap<>();
                params.put("sgId",distributor);
                params.put("customerId",customerId);
                dongGoodsDao.bindCustomerSg(params);
                sgId = distributor;
            }
        }
        //支付角色
        Integer payRole = 5;
        String cusIndextity = dongGoodsDao.getUserIdentity(customerId);
        if(("1").equals(cusIndextity)){
            payRole = 4;
        }else if(!("0").equals(cusIndextity)){
            payRole = 2;
        }
        //机构大B UID
        String orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
        //通联提现账户
        String withdrawUid = "#yunBizUserId_B2C#";
        // 直接购买小b商品，产生推荐费和服务费
        Long id = Long.valueOf(totalFee.get("goodsId").toString());
        //skuId
        Long skuId = null;
        if(totalFee.get("skuId")!=null){
            skuId = Long.valueOf(totalFee.get("skuId").toString());
        }
        Long recId = Long.valueOf(totalFee.get("recId").toString());
        //商品购买数量
        Integer goodsNum = Integer.valueOf(totalFee.get("goodsNum").toString());
        //商品运费
        Long shippingFee = Long.valueOf(totalFee.get("shippingFee").toString());
        GoodsParamPo goodsParamPo = goodsService.getGoodsParamPoByGoodsId(id);
        //是否反润
        Integer type =  goodsParamPo.getType();
        //关联供货商品ID(判断是不是销售商品)
        Long mallsGoodsId =  goodsParamPo.getMallsGoodsId();
        //供货商机构
        String mallsOrgId=orgId;
        //供货商商品的belongId，为空则是大b
        String mallsBelongId = "";
        //销售商小B
        String belongId = purchaseProcessDao.getBelongIdByGoodsId(id);
        // 小b和大b要去查uid
        String belongUid = purchaseProcessDao.getAccountUidByCustomerId(belongId);
        //是不是销售商品
        boolean isSale = false;
        if(!StringUtils.isEmpty(mallsGoodsId)){
            isSale = true;
        }
        //供货商品供货价
        Integer mallsGoodsPrice =  0;
        //供货商品总价格
        Integer mallsGoodsTotalPrice = 0;
        //是否亏损
        Integer isLoss = 0;
        if(isSale){
            //获取商品信息
            GoodsParamPo mallsGoodsParamPo = goodsService.getGoodsParamPoByGoodsId(mallsGoodsId);
            mallsOrgId = mallsGoodsParamPo.getOrgId();
            mallsBelongId =  mallsGoodsParamPo.getBelongId();
            Long mallSkuId = null;
            if (skuId != null) {
                //通过商品ID和SKUID去缓存中拿取mallsskuid
                mallSkuId = goodsService.getCreateOrderMallsSkuId(id, skuId);
            }
            //获取供货商价格
            mallsGoodsPrice= goodsService.getCreateOrderMallsAmount(id,skuId);
            mallsGoodsTotalPrice = mallsGoodsPrice * goodsNum + shippingFee.intValue();
        }
        //懂小姐返润设置
        Map<String, Object> reverseProfitModel = dongGoodsDao.getReverseProfitModel(orgId);
        //商品返润比例
        //Integer rebate = purchaseProcessDao.getPromotionRebateByGoodsId(id);
        String rebateStr = purchaseProcessDao.getPromotionStrRebateByGoodsId(id);// 总返利,eg:20
        if (StringUtils.isEmpty(rebateStr)) {
            rebateStr = "0";
        }
        Double rebate = Double.valueOf(rebateStr);
        //服务费，分享人获得
        Double serviceRate =  Double.valueOf(reverseProfitModel.get("serviceFee").toString());
        //推荐费，用户锁定导购获得
        Double recommendRate =  Double.valueOf(reverseProfitModel.get("recommendFee").toString());
        //绑定费，用户绑定搭配师获得
        Double bindRate =  Double.valueOf(reverseProfitModel.get("bindFee").toString());
        //商品代理搭配师获得
        Double agencyRate = Double.valueOf(reverseProfitModel.get("agencyFee").toString());
        //平台服务费
        Double platformServiveRate = Double.valueOf(reverseProfitModel.get("platformServiceFee").toString());
        //联汇抽成
        Map<String, String> platformRateMap = purchaseProcessDao.getPlatformRateByOrgId(orgId);
        tradeInfoPo.setPlatformRateMap(platformRateMap);
        Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
        //大b抽成
        Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));
        //商品价格
        Long goodsAmount = Long.valueOf(totalFee.get("goods").toString());
        //订单价格
        Long orderAmount = Long.valueOf(totalFee.get("order").toString());
        //返润金额
        Long baseFee = getFeeByRate(customerId,goodsAmount,rebate,100.00);
        //获取用户绑定搭配师
        String dsId = dongGoodsDao.getBindDsId(customerId);
        //可用积分不为null
        if (score != null) {
            // 如果要使用积分
            double v = goodsAmount - baseFee;
            // 可用积分，直接取整
            int l = (int) v;
            if (score > l) {
                // 可使用积分限制
                score = l;
            }
        } else {
            score = 0;
        }
        totalFee.put("score", score.longValue());
        // 用户实付金额
        Long pay = orderAmount - Long.valueOf(score);
        totalFee.put("pay",pay);
        //=============商品服务费分润开始
        //服务费
        Long serviceFee = getFeeByRate(distributor,goodsAmount,rebate,serviceRate);
        //推荐费
        Long recommendFee = getFeeByRate(sgId,goodsAmount,rebate,recommendRate);
        //绑定费
        Long bindFee = getFeeByRate(dsId,goodsAmount,rebate,bindRate);
        //代理费
        Long agencyFee = getFeeByRate(designerId,goodsAmount,rebate,agencyRate);
        //平台服务费 = 返润 - 服务费 - 推荐费 - 绑定费 - 代理费
        Long platformServiceFee = baseFee-serviceFee-recommendFee-bindFee-agencyFee;
        //=============商品服务费分润结束
        //联汇抽成
        Long linkTakeFee = getFeeByRate(customerId,pay,100.00,Double.valueOf(linkerTake));
        //大B抽成
        Long unionBarleyTakeFee = getFeeByRate(customerId,pay,100.00,Double.valueOf(unionBarleyTake));
        //平台抽成 = 联汇抽成 + 大B抽成
        Long platformTakeFee = linkTakeFee+unionBarleyTakeFee;
        if(isSale){
            //供货商的ID和通联ID
            String mallsOrgUid = stringRedisTemplate.opsForValue().get("orgUid:"+mallsOrgId);
            if(StringUtils.isEmpty(mallsOrgUid)){
                mallsOrgUid =  purchaseProcessDao.getAccountUidByOrgId(mallsOrgId);
                stringRedisTemplate.opsForValue().set("orgUid:"+mallsOrgId,mallsOrgUid);
            }
            String mallsBelongUid = "";
            if(!StringUtils.isEmpty(mallsBelongId)){
                mallsBelongUid = stringRedisTemplate.opsForValue().get("belongUid:"+mallsBelongId);
                if(StringUtils.isEmpty(mallsBelongUid)){
                    mallsBelongUid = purchaseProcessDao.getAccountUidByCustomerId(mallsBelongId);
                    stringRedisTemplate.opsForValue().set("belongUid:"+mallsBelongId,mallsBelongUid);
                }
            }
            String ghsfrom = StringUtils.isEmpty(mallsBelongId) ? mallsOrgId : mallsBelongId;
            String ghsfromUid = StringUtils.isEmpty(mallsBelongId) ? mallsOrgUid : mallsBelongUid;
            Integer ghsRole = StringUtils.isEmpty(mallsBelongId) ? 1 : 2;
            String xssId = belongId;
            Integer xssRole = 2;
            if(!"smallB".equals(userType)){
                xssId = orgId;
                xssRole = 1;
            }
            //供货商商品成交（收入）= 推广价格x商品数量（多个商品相加）+运费（多个商品相加）
            Long mallGoodsGet = orderAmount;// - platformTakeFee;
            Map<String,Object> recommendTrade = getTradeInfo(customerId,ghsfrom,mallGoodsGet,TradeTypeConstants.DEAL_FEE,-1,ghsRole,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(recommendTrade);
            //供货商推广佣金（支出）= 推广价格x商品数量（多个商品相加）+运费（多个商品相加）-供货价x商品数量（多个商品相加）-供货运费（多个商品相加）
            Long mallGoodsTg = orderAmount - mallsGoodsTotalPrice;
            //供货商通联所得
            Long mallsTlAmount = mallGoodsGet - mallGoodsTg - platformTakeFee;
            if(mallsTlAmount<0L){
                mallsTlAmount = 0L;
                isLoss = 1;
            }
            if(mallsTlAmount!=0){
                Map<String, Object> recommendItem = new HashMap<>();
                if(orgUid.equals(ghsfromUid)){
                    recommendItem.put("type",1);
                }else{
                    recommendItem.put("type",0);
                }
                recommendItem.put("customerId", ghsfromUid);
                recommendItem.put("splitAmount", mallsTlAmount);
                recommendItem.put("note", "供货商所得");
                recommendItem.put("orderId", orderSn);
                cashSplitItems.add(recommendItem);
            }
            //供货商交易手续费（平台抽成）支出
            Map<String,Object> platformTakeTrade = getTradeInfo(ghsfrom,null,platformTakeFee, TradeTypeConstants.TRADE_SERVER_FEE,ghsRole,-1,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(platformTakeTrade);
            //销售商推广佣金（收入）= 推广价格x商品数量（多个商品相加）-供货价x商品数量（多个商品相加）
            Long saleGoodsTg = orderAmount - mallsGoodsTotalPrice;
            Map<String,Object> tgTrade = getTradeInfo(ghsfrom,xssId,saleGoodsTg, TradeTypeConstants.SPREAD_FEE,ghsRole,xssRole,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(tgTrade);
            //销售商商品成交（收入）= 推广价格x商品数量（多个商品相加）+运费（多个商品相加）
            Long saleGoodsGet = orderAmount;
            Map<String,Object> getTrade = getTradeInfo(customerId,xssId,saleGoodsGet, TradeTypeConstants.DEAL_FEE,-1,xssRole,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(getTrade);
            //销售商采购（支出）= 推广价格x商品数量（多个商品相加）+运费（多个商品相加）
            Long saleGoodsBuy = orderAmount;
            Map<String,Object> buyTrade = getTradeInfo(xssId,null,saleGoodsBuy, TradeTypeConstants.PURCHASE_FEE,xssRole,-1,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(buyTrade);
            //销售商返润佣金（支出）
            Long saleGoodsCommission = baseFee;
            Map<String,Object> commissionTrade = getTradeInfo(xssId,null,saleGoodsCommission, TradeTypeConstants.REJUVENATE_FEE,xssRole,-1,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(commissionTrade);
            //销售商通联所得
            Long xssTlget = orderAmount - mallsTlAmount - baseFee - platformTakeFee;
            if(xssTlget!=0){
                Map<String, Object> recommendItem = new HashMap<>();
                String xxsUid = orgUid;
                if("smallB".equals(userType)){
                    xxsUid = belongUid;
                }
                recommendItem.put("customerId", xxsUid);
                if(orgUid.equals(xxsUid)){
                    recommendItem.put("type",1);
                }else{
                    recommendItem.put("type",0);
                }
                recommendItem.put("splitAmount", xssTlget);
                recommendItem.put("note", "销售商所得");
                recommendItem.put("orderId", orderSn);
                cashSplitItems.add(recommendItem);
            }
        }else{
            //商品成交收益
            Long goodsGet = orderAmount-baseFee-platformTakeFee;
            Map<String, Object> goodsGetItem = new HashMap<>();
            goodsGetItem.put("note", "商品收益");
            goodsGetItem.put("orderId", orderSn);
            goodsGetItem.put("splitAmount", goodsGet);
            String xxs = orgId;
            String xxsUid = orgUid;
            Integer xxsRole = 1;
            if("smallB".equals(userType)){
                xxs = belongId;
                xxsUid = belongUid;
                xxsRole = 2;
            }
            goodsGetItem.put("customerId", xxsUid);
            if(orgUid.equals(xxsUid)){
                goodsGetItem.put("type",1);
            }else{
                goodsGetItem.put("type", 0);
            }
            cashSplitItems.add(goodsGetItem);
            Map<String,Object> orderAmountTrade = getTradeInfo(customerId,xxs,orderAmount,TradeTypeConstants.DEAL_FEE,payRole,xxsRole,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(orderAmountTrade);
            Map<String,Object> tgTrade = getTradeInfo(xxs,null,baseFee, TradeTypeConstants.REJUVENATE_FEE,xxsRole,-1,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(tgTrade);
            Map<String,Object> platformTakeTrade = getTradeInfo(xxs,null,platformTakeFee, TradeTypeConstants.TRADE_SERVER_FEE,xxsRole,-1,
                    "goodsGet",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(platformTakeTrade);
        }
        //生成所有交易记录
        //服务费
        if(serviceFee!=0&&StringUtil.isNotEmpty(distributor)){
            String receiveUserId = distributor;
            String dReceiveRole = distributorId;
            String oldDReceiveId = null;
            String oldDReceiveRole = null;
            Integer payType = 1;//1现金  2积分
            Integer tradeType = 2;//现金记录表商品服务费交易类型为2
            if(serviceScore){
                payType = 2;
                tradeType = 1;//积分记录表商品服务费交易类型为2
            }else{
                //获取搭配师身份信息
                if(("2").equals(distributorId)){
                    WxUserIdentityPo dsIdenInfo = dongGoodsDao.getUserIdentityInfo(distributor);
                    Map<String,Object> params = new HashMap<>();
                    params.put("walletUserId",distributor);
                    params.put("walletType",3);//1、体检返佣  2、代理费  3、服务费  4、服饰券核销
                    Integer walletSet= dongGoodsDao.getCustomerWalletSet(params);
                    if(walletSet!=null&&walletSet==0) {
                        //分给渠道商
                        receiveUserId = dsIdenInfo.getCpId();
                        dReceiveRole="3";
                        oldDReceiveId = distributor;
                        oldDReceiveRole = "2";
                    }
                }
            }
            Map<String, Object> serviceItem = new HashMap<>();
            //通联所有分账都给平台，提现时再将前提给个人
            serviceItem.put("customerId", withdrawUid);
            serviceItem.put("splitAmount", serviceFee);
            serviceItem.put("note", "商品收益-服务费");
            serviceItem.put("orderId", orderSn);
            serviceItem.put("type",0);
            cashSplitItems.add(serviceItem);
            Map<String,Object> serviceTrade = getTradeInfo(customerId,receiveUserId,serviceFee,tradeType,payRole,5,
                    "service",payType,dReceiveRole,oldDReceiveId,oldDReceiveRole,goodsName,recId,isLoss);
            tradeInfos.add(serviceTrade);
        }else{
            platformServiceFee = platformServiceFee + serviceFee;
        }
        //推荐费
        if(recommendFee!=0&&StringUtil.isNotEmpty(sgId)){
            Map<String, Object> recommendItem = new HashMap<>();
            //通联所有分账都给平台，提现时再将前提给个人
            recommendItem.put("customerId", withdrawUid);
            recommendItem.put("splitAmount", recommendFee);
            recommendItem.put("note", "商品收益-推荐费");
            recommendItem.put("orderId", orderSn);
            recommendItem.put("type",0);
            cashSplitItems.add(recommendItem);
            Map<String,Object> recommendTrade = getTradeInfo(customerId,sgId,recommendFee,3,payRole,4,
                    "recommend",1,"2",null,null,goodsName,recId,isLoss);
            tradeInfos.add(recommendTrade);
        }else{
            platformServiceFee = platformServiceFee + recommendFee;
        }
        //绑定费
        if(bindFee!=0&&StringUtil.isNotEmpty(dsId)){
            Map<String, Object> bindItem = new HashMap<>();
            //通联所有分账都给平台，提现时再将前提给个人
            bindItem.put("customerId", withdrawUid);
            bindItem.put("splitAmount", bindFee);
            bindItem.put("note", "商品收益-绑定费");
            bindItem.put("orderId", orderSn);
            bindItem.put("type", 0);
            cashSplitItems.add(bindItem);
            Map<String,Object> bindTrade = getTradeInfo(customerId,dsId,bindFee,3,payRole,-2,
                    "bind",1,"2",null,null,goodsName,recId,isLoss);
            tradeInfos.add(bindTrade);
        }else{
            platformServiceFee = platformServiceFee + bindFee;
        }
        //代理费
        if(agencyFee!=0&&StringUtil.isNotEmpty(designerId)){
            String receiveUserId = designerId;
            String dReceiveRole = "2";
            String oldDReceiveId = null;
            String oldDReceiveRole = null;
            Map<String,Object> params = new HashMap<>();
            params.put("walletUserId",designerId);
            params.put("walletType",2);//1、体检返佣  2、代理费  3、服务费  4、服饰券核销
            Integer walletSet= dongGoodsDao.getCustomerWalletSet(params);
            if(walletSet!=null&&walletSet==0) {
                //获取搭配师身份信息
                WxUserIdentityPo dsIdenInfo = dongGoodsDao.getUserIdentityInfo(designerId);
                //分给渠道商
                receiveUserId = dsIdenInfo.getCpId();
                dReceiveRole = "3";
                oldDReceiveId = designerId;
                oldDReceiveRole = "2";
            }
            Map<String, Object> agencyItem = new HashMap<>();
            //通联所有分账都给平台，提现时再将前提给个人
            agencyItem.put("customerId", withdrawUid);
            agencyItem.put("splitAmount", agencyFee);
            agencyItem.put("note", "商品收益-代理费");
            agencyItem.put("orderId", orderSn);
            agencyItem.put("type", 0);
            cashSplitItems.add(agencyItem);
            Map<String,Object> agencyTrade = getTradeInfo(customerId,receiveUserId,agencyFee,3,payRole,-2,
                    "agency",1,dReceiveRole,oldDReceiveId,oldDReceiveRole,goodsName,recId,isLoss);
            tradeInfos.add(agencyTrade);
        }else{
            platformServiceFee = platformServiceFee + agencyFee;
        }
        //大B平台费
        //平台费 = 大B抽成 + 平台服务费
        Long platformFee = unionBarleyTakeFee+platformServiceFee;
        if((platformFee)!=0&&StringUtil.isNotEmpty(orgId)){
            Map<String, Object> platformItem = new HashMap<>();
            platformItem.put("customerId", orgUid);
            platformItem.put("splitAmount", platformFee);
            platformItem.put("note", "商品收益-平台费");
            platformItem.put("orderId", orderSn);
            platformItem.put("type", 1);
            cashSplitItems.add(platformItem);
            Map<String,Object> agencyTrade = getTradeInfo(customerId,orgId,platformServiceFee,TradeTypeConstants.GOODS_PLATFORM_FEE,payRole,1,
                    "dongService",1,"5",null,null,goodsName,recId,isLoss);
            tradeInfos.add(agencyTrade);
            Map<String,Object> unionBarleyTakeFeeTrade = getTradeInfo(customerId,orgId,unionBarleyTakeFee,TradeTypeConstants.PAY_CENTAGE_FEE,payRole,1,
                    "dongService",1,"5",null,null,goodsName,recId,isLoss);
            tradeInfos.add(unionBarleyTakeFeeTrade);
        }
        //联汇抽成
        //每个机构一个联汇子账号
        String linkId = purchaseProcessDao.getLinkIdByOrgId(orgId);
        if (payMode==2&&StringUtils.isEmpty(linkId)) {
            //通联模式下联汇资金子账号必须有
            throw GlobalException.build("联汇子账号暂未绑定");
        }
        if(linkTakeFee!=0&&StringUtil.isNotEmpty(linkId)){
            Map<String, Object> linkTakeItem = new HashMap<>();
            linkTakeItem.put("customerId", linkId);
            linkTakeItem.put("splitAmount", linkTakeFee);
            linkTakeItem.put("note", "商品收益-联汇抽成费");
            linkTakeItem.put("orderId", orderSn);
            linkTakeItem.put("type", 0);
            cashSplitItems.add(linkTakeItem);
            Map<String,Object> linkTakeTrade = getTradeInfo(customerId,linkId,linkTakeFee,9,payRole,0,
                    "link",1,null,null,null,goodsName,recId,isLoss);
            tradeInfos.add(linkTakeTrade);
        }
        //大B抽成
//        Map<String,Object> unionBarleyTrade = getTradeInfo(customerId,orgId,unionBarleyTakeFee,4,1,"unionBarley");
//        tradeInfos.add(unionBarleyTrade);
        tradeInfoPo.setCashSplitItems(cashSplitItems);
        tradeInfoPo.setCommissionTradeInfo(tradeInfos);
        return tradeInfoPo;
    }

    /**
     * 生成微信支付调用参数
     */
    private Map<String, Object> getWxPayParam(String openId, String orderSn, String totalFee, String orgId) {
        String notifyUrl = systemProperties.getScrmUrl() + "dong/paycallback";
        String wcpayType = "STEPLINK_MISS_" + orgId;
        Map<String, String> params = new HashMap<>();
        params.put("body", "懂小姐商品订单");
        params.put("notifyUrl", notifyUrl);
        params.put("openid", openId);
        params.put("outTradeNo", orderSn);
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        params.put("totalFee", totalFee);
        params.put("tradeType", "JSAPI");
        params.put("wcpayType", wcpayType);
        Map<String, String> appSign = ParamSignUtils.sign(params);
        params.put("appSign", appSign.get("appSign"));
        Map<String, Object> result = new HashMap<>(params);
        return result;
    }

    /**
     * 调用结果处理(微信)
     */
    public String callResultProcessWx(String result) throws GlobalException {
        if (StringUtils.isEmpty(result)) {
            throw GlobalException.build("网关调用失败");
        }
        Object parse = JSON.parse(result);
        Map ret = (Map) parse;
        if ((Integer) ret.get("rt") != 1) {
            throw GlobalException.build("支付网关调用失败");
        }
        //noinspection unchecked
        Map<String, Object> retInfo = (Map) ret.get("object");
        retInfo.put("package", "prepay_id=" + retInfo.get("prepayId"));
        return JSON.toJSONString(retInfo);
    }

    /**
     * 调用结果处理(中金)
     */
    public String callResultProcessTL(String result) throws GlobalException {
        if (StringUtils.isEmpty(result)) {
            throw GlobalException.build("网关调用失败");
        }
        Map resMap = (Map) JSON.parse(result);
        if (!resMap.containsKey("code")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!"200".equals(resMap.get("code"))) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!resMap.containsKey("data")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        Map data = (Map) resMap.get("data");
        if (!data.containsKey("authCode")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        return (String) data.get("authCode");
    }

    //生成费用
    private Long getFeeByRate(String customerId,Long amount,Double baseRate,Double serviceRate){
        Long getFee = 0L;
        if(StringUtil.isNotEmpty(customerId)){
            //存在分佣人，产生服务费
            double fee = amount * baseRate * serviceRate / 100 / 100;
            getFee = new BigDecimal(fee).setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();
        }
        return getFee;
    }

    //生成交易记录
    private Map<String,Object> getTradeInfo(String from,String to,Long amount,Integer tradeType,Integer payRole,
                                            Integer receiveRole,String dongTradeType,Integer payType,
                                            String dReceiveRole,String oldDReceiveId,String oldDReceiveRole,String goodsName,Long recId,Integer isLoss){
        if(!amount.equals(0L)){
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", from);
            tradeInfo.put("to", to);
            tradeInfo.put("amount", amount);
            tradeInfo.put("tradeType", tradeType);
            tradeInfo.put("isKnowledge", 0);
            tradeInfo.put("recId", recId);
            tradeInfo.put("payType", payType);//1：现金 2：积分
            tradeInfo.put("payRole", payRole);
            tradeInfo.put("receiveRole", receiveRole);
            tradeInfo.put("accountType", null);
            tradeInfo.put("receiveAccount", "");
            tradeInfo.put("dongTradeType", dongTradeType);
            tradeInfo.put("dReceiveRole", dReceiveRole);
            tradeInfo.put("oldDReceiveId", oldDReceiveId);
            tradeInfo.put("oldDReceiveRole", oldDReceiveRole);
            tradeInfo.put("goodsName", goodsName);
            tradeInfo.put("isLoss", isLoss);
            return tradeInfo;
        }else{
            return null;
        }
    }

    /**
     * 购买商品回调
     *
     * @param param
     * @throws GlobalException
     */
    @Transactional(propagation= Propagation.SUPPORTS)
    protected void shopCallback(Map<String, Object> param) throws GlobalException {
        String orderSn = (String) param.get("orderSn");
        LOGGER.warn("懂小姐支付订单回调,orderSn===[{}]", orderSn);
        Integer count = purchaseProcessDao.countTradeByOrderSn(orderSn);
        if (count > 0) {
            throw GlobalException.build("该订单已支付完成");
        }
        List<Map<String, Object>> goodsIdAndBuyNum = purchaseProcessDao.getGoodsIdAndBuyNumByOrderSn(orderSn);
        for (Map<String, Object> map : goodsIdAndBuyNum) {
            purchaseProcessNewService.addSaleNum(map);
        }
        Map<String, Object> orderInfo = purchaseProcessDao.getOrderInfoByOrderSn(orderSn);
        String customerId = (String) orderInfo.get("customerId");
        String orgId = (String) orderInfo.get("orgId");
        String wxtransactionId = (String) param.get("txsn");
        // 更新订单状态
        purchaseProcessDao.updateOrderInfo((String) param.get("txsn"),1,20,orderSn);

        //region edit ckq  2020-06-10 修改update直接先查orderid 在update
        Integer orderId = purchaseProcessDao.getOrderIdByOrderSn(orderSn);
        if(StringUtils.isEmpty(orderId)){
            throw GlobalException.build("通过orderSn获取orderId失败");
        }
        //endregion
        // 更新商品订单状态
        purchaseProcessDao.updateMerchantOrderGoodsInfo(1,orderId);
        // 冻结时间
        //懂小姐返润设置
        Map<String, Object> reverseProfitModel = dongGoodsDao.getReverseProfitModel(orgId);
//        Integer freezeTime = Integer.valueOf(reverseProfitModel.get("freezeTime").toString());
//        if (freezeTime == null || freezeTime < 0) {
//            freezeTime = 30;
//        }
        /**
         * @Modify: 锋
         * @Date: 2020/3/25 9:28
         * @Description: 懂小姐商品订单暂时调整为直接结算
         * @Version: 懂小姐1.1.2
         */
        Integer freezeTime = 0;
        // 解冻时间
        String unFreezeTime = df.format(LocalDateTime.now()
                .plusDays(freezeTime));
        // redis取分账信息
        String info = stringRedisTemplate.opsForValue().get(DONG_CREATE_ORDER_INFO + orderSn);
        if (StringUtils.isEmpty(info)) {
            throw GlobalException.build("该订单已过期");
        }
        //通联支付直接下发金额
        Integer payMode = mallService.getPayModeByOrgId(orgId);
        if (payMode == 2) {
            // 测试环境用yt
            String alias = getAlias(orgId);
            Map<String, Object> reqMap = new HashMap<>();
            reqMap.put("clintType", alias);
            // 手续费
            reqMap.put("orderSn", orderSn);
            String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_SIGNAL_AGENT_PAY;
            // 请求支付网关
            try {
                String result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
                LOGGER.warn("懂小姐支付订单回调,result===[{}]", result);
            } catch (Exception e) {
                throw GlobalException.build("支付网关调用异常");
            }
        }
        List<TradeInfo> tradeInfoList = JSON.parseArray(info, TradeInfo.class);
        for (TradeInfo tradeInfo : tradeInfoList) {
            if(tradeInfo!=null){
                Integer payType = tradeInfo.getPayType();
                switch (payType) {
                    case 1: {
                        // 现金
                        String to = tradeInfo.getTo();
                        Integer receiveRole = tradeInfo.getReceiveRole();
                        Integer balance;
                        switch (receiveRole) {
                            // 根据收款人角色，判断给哪个表加，在哪个表查余额。
                            // 先加，再取余额，再记录
                            case 0:
                                balance = 0;
                                break;
                            case 1:
                                // 大b
                                purchaseProcessDao.updateOrgAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                                break;
                            case 2:
                                // 小b
                                purchaseProcessDao.updateSalesAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                                stringRedisTemplate.delete("home:customer_info_" + to);
                                break;
                            case -2:
                            case 3:
                            case 4:
                            case 5:
                                if(tradeInfo.getReceiveRole() == -2){
                                    tradeInfo.setReceiveRole(2);
                                }
                                // 普通用户
                                purchaseProcessDao.updateCustomerAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getUserBalanceByCustomerId(to);
                                stringRedisTemplate.delete("home:customer_info_" + to);
                                break;
                            default:
                                balance = 0;
                                break;
                        }
                        Map<String, Object> map = new HashMap<>();
                        map.put("payMode", payMode);
                        map.put("orgId", orgId);
                        map.put("balance", balance);
                        map.put("orderSn", orderSn);
                        map.put("tradeInfo", tradeInfo);
                        map.put("unFreezeTime", unFreezeTime);
                        // 生成业务单号
                        String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                        map.put("busiSn", busiSn);
                        map.put("serialNo", wxtransactionId);
                        purchaseProcessDao.insertDongTradeInfo(map);
                        purchaseProcessDao.insertDongProtectTradeInfo(map);
                        //插入懂小姐交易记录
                        Map<String, Object> dongTrade = new HashMap<>();
                        dongTrade.put("orgId", orgId);
                        dongTrade.put("orderSn", orderSn);
                        dongTrade.put("serialNo", wxtransactionId);
                        dongTrade.put("payUser", tradeInfo.getFrom());
                        dongTrade.put("receiveUser", tradeInfo.getTo());
                        dongTrade.put("amount", tradeInfo.getAmount());
                        dongTrade.put("payRole", 0);
                        dongTrade.put("receiveRole", tradeInfo.getDReceiveRole());
                        dongTrade.put("oldDReceiveId", tradeInfo.getOldDReceiveId());
                        dongTrade.put("oldDReceiveRole", tradeInfo.getOldDReceiveRole());
                        switch (tradeInfo.getDongTradeType()) {
                            case "service":
                            case "recommend":
                            case "bind":
                            case "agency":
                            case "dongService":
                                dongGoodsDao.insertDongTradeInfo(dongTrade);
                                break;
                            case "link":
                                break;
                            case "unionBarley":
                                break;
                            case "goodsGet":
                                break;
                            default:
                                break;
                        }
                        break;
                    }
                    case  2:{
                        // 积分
                        String to = tradeInfo.getTo();
                        Integer amount = tradeInfo.getAmount();
                        Integer receiveRole = tradeInfo.getReceiveRole();
                        Integer balance;
                        switch (receiveRole) {
                            // 根据收款人角色，判断给哪个表加，在哪个表查余额。
                            // 先加，再取余额，再记录
                            case 5:
                                // 目前只有普通用户会拿到积分
                                purchaseProcessDao.addScoreByCustomerId(Long.valueOf(amount),to);
                                balance = purchaseProcessDao.getCustomerScoreBalanceByCustomerId(to);
                                break;
                            default:
                                balance = 0;
                                break;
                        }
                        Map<String, Object> map = new HashMap<>();
                        map.put("orgId", orgId);
                        map.put("balance", balance);
                        map.put("orderSn", orderSn);
                        map.put("tradeInfo", tradeInfo);
                        map.put("unFreezeTime", unFreezeTime);
                        // 生成业务单号
                        String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                        map.put("busiSn", busiSn);
                        map.put("serialNo", wxtransactionId);
                        purchaseProcessDao.insertTradeScoreInfo(map);
                        //插入懂小姐交易记录
                        Map<String, Object> dongTrade = new HashMap<>();
                        dongTrade.put("orgId", orgId);
                        dongTrade.put("payUser", tradeInfo.getFrom());
                        dongTrade.put("receiveUser", to);
                        dongTrade.put("amount", amount);
                        dongTrade.put("type", 4);
                        dongTrade.put("payRole", 0);
                        dongTrade.put("receiveRole", 0);
                        dongGoodsDao.insertDongScoreTradeInfo(dongTrade);
                        break;
                    }
                    default:
                        break;
                }

            }
        }
    }

    /**
     * 生成业务单号
     * 前缀+13位时间戳+用户id
     */
    public String generateBusiSn(Integer tradeType, String customerId) {
        String prefix = "";
        switch (tradeType) {
            // rmb交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费(大b)，5-开通联盟商家平台费，
            // 6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商品平台费(联汇)，10-商城商品收益，11-提现手续费
            case 1:
            case 10:
                prefix = "AB";
                break;
            case 2:
                prefix = "AE";
                break;
            case 3:
                prefix = "AF";
                break;
            case 4:
                prefix = "AC";
                break;
            case 5:
                prefix = "BD";
                break;
            case 6:
                prefix = "BB";
                break;
            case 7:
                prefix = "CD";
                break;
            case 8:
                prefix = "CB";
                break;
            case 9:
                prefix = "AD";
                break;
            case 12:
                prefix = "F";
                break;
            default:
                break;
        }
        return prefix + System.currentTimeMillis() + customerId;
    }

    private void zeroBuy(String orderSn){
        Map<String, Object> map = new HashMap<>();
        map.put("orderSn", orderSn);
        map.put("txsn", "");
        this.shopCallback(map);
    }

    /**
     * 确认订单
     */
    public Object checkOrder(Map<String, Object> param) {
        String customerId = (String) param.get("customerId");
        String orgId = (String) param.get("orgId");
        // 剩余积分
        Integer score = purchaseProcessDao.getScoreByCustomerId(customerId);
        Integer goodsId = (Integer) param.get("goodsId");
        Integer buyCount = (Integer) param.get("buyCount");
        String shoppingCartIds = (String) param.get("shoppingCartIds");
        Integer goodsNum = 0;
        Long goodsAmountCent = 0L;
        Long baseFee = 0L;
        Double goodsAmount = 0.00;
        Double orderAmount = 0.00;
        Double orderTotalPrice = 0.00;
        Double goodsFreight = 0.00;
        List<ShoppingCartPo> shoppingCartPos;
        CheckMerchantOrderPo orderPo = new CheckMerchantOrderPo();
        orderPo.setScore(score);
        orderPo.setScoreAble(score);
        List<ShoppingCartGoodsPo> goodsPoList = new ArrayList<>();
        if (goodsId != null && goodsId != 0 && buyCount != null && buyCount != 0) {
            // 直接购买联盟商家的商品，需要计算最大可抵扣积分
            ShoppingCartGoodsPo goodsPo = mallDao.checkShoppingGoodsOrder(param);
            goodsPo.setBuyCount(buyCount);
            goodsNum = goodsNum + goodsPo.getBuyCount();
            //商品价格
            goodsAmount = goodsAmount + goodsPo.getAmount() * goodsPo.getBuyCount();
            goodsAmountCent = goodsPo.getAmountCent() * goodsPo.getBuyCount();
            //订单价格
            orderAmount = orderAmount + goodsPo.getAmount() * goodsPo.getBuyCount();
            //订单总价
            orderTotalPrice = orderTotalPrice + goodsPo.getAmount() * goodsPo.getBuyCount();
            //商品返润比例
            Integer rebate = purchaseProcessDao.getPromotionRebateByGoodsId(Long.valueOf(goodsId));
            //返润金额
            baseFee = baseFee + getFeeByRate(customerId,goodsAmountCent,Double.valueOf(rebate),100.00);
            goodsPoList.add(goodsPo);
        } else if (!StringUtils.isEmpty(shoppingCartIds)) {
            // 购物车购买
            orderPo.setType(1);
            String[] split = shoppingCartIds.split(",");
            param.put("shoppingCartIds", split);
            shoppingCartPos = mallDao.checkShoppingCartOrder(param);
            for (ShoppingCartPo cartPo : shoppingCartPos) {
                for (ShoppingCartGoodsPo goodsPo : cartPo.getGoodsList()) {
                    goodsNum = goodsNum + goodsPo.getBuyCount();
                    //商品价格元
                    goodsAmount = goodsAmount + goodsPo.getAmount() * goodsPo.getBuyCount();
                    //分
                    goodsAmountCent = goodsPo.getAmountCent() * goodsPo.getBuyCount();
                    //订单价格元
                    orderAmount = orderAmount + goodsPo.getAmount() * goodsPo.getBuyCount();
                    orderTotalPrice = orderTotalPrice + goodsPo.getAmount() * goodsPo.getBuyCount();
                    if (goodsPo.getGoodsFreight() > goodsFreight) {//取运费最大
                        goodsFreight = goodsPo.getGoodsFreight();
                    }
                    if (!StringUtils.isEmpty(goodsPo.getBelongId())) {
                        orderPo.setType(0);
                    }
                    //商品返润比例
                    Integer rebate = purchaseProcessDao.getPromotionRebateByGoodsId(Long.valueOf(goodsId));
                    baseFee = baseFee + getFeeByRate(customerId,goodsAmountCent,Double.valueOf(rebate),100.00);
                }
            }
            if (shoppingCartPos.size() > 0) {
                goodsPoList = shoppingCartPos.get(0).getGoodsList();
            }
        }
        //可用积分不为null
        if (score != null) {
            // 如果要使用积分
            Long v = goodsAmountCent - baseFee;
            // 可用积分，直接取整
            if (score > v.intValue()) {
                // 可使用积分限制
                score = v.intValue();
            }
        } else {
            score = 0;
        }
        orderPo.setScoreAble(score);
        DecimalFormat df = new DecimalFormat("#.00");
        //分转元
        double s = ((double) score/100);
        Double scoreAmount = Double.valueOf(df.format(s));
        orderPo.setOrderScoreAmount(orderAmount - scoreAmount);
        orderTotalPrice = orderTotalPrice + goodsFreight;
        orderAmount = orderAmount + goodsFreight;
        orderPo.setGoodsAmount(new BigDecimal(goodsAmount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderPo.setOrderAmount(new BigDecimal(orderAmount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderPo.setOrderTotalPrice(new BigDecimal(orderTotalPrice).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderPo.setGoodsNum(goodsNum);
        orderPo.setShippingFee(new BigDecimal(goodsFreight).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        if (goodsPoList.size() > 0) {
            orderPo.setGoodsList(goodsPoList);
        }
        return orderPo;
    }

    /**
     * 判断h5是否已开户
     *
     * @param param 参数
     *              customerID
     *              openId
     *              orgId
     * @return
     */
    public void checkCustomerAccount(Map<String, Object> param) {
        param.put("acctType", "XCX");
        param.put("clintType", getAlias(param.get("orgId").toString()));
        // 判断小程序用户 开户
        Integer cCount = maiBaoLaDao.checkCustomerAccount(param);
        if (cCount < 1) {
            // 调用个人H5开户
            param.put("source", "1");
            createMember(param);
        } else {
            // 判断 用户绑定支付标识
            Integer count = maiBaoLaDao.checkCustomerAccountIden(param);
            if (count < 1) {
                // 调用 用户绑定支付标识
                applyBindAcct(param);
            }
        }
    }

    /**
     * 获取 应用别名
     *
     * @param orgId
     * @return
     */
    public String getAlias(String orgId) {
        Integer payMode = maiBaoLaDao.getPayModeByOrgId(orgId);
        if (payMode == 1) {
            return "";
        }
        String alias = maiBaoLaDao.getAlias(orgId);
        if (StringUtils.isEmpty(alias)) {
            throw GlobalException.build("请先设置应用别名");
        }
        return alias;
    }

    /**
     * 个人H5开户
     *
     * @param map
     */
    private void createMember(Map<String, Object> map) {
        try {
            String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_CREATE_MEMBER, JSON.toJSONString(map), WcPayConstant.JSON);
            if (null != result) {
                JSONObject object = JSONObject.parseObject(result);
                if (("200").equals(object.getString("code"))) {
                    String statusCode = object.getJSONObject("data").getString("status");
                    if ("20".equals(statusCode)) {
                        throw GlobalException.build("个人H5开户处理中");
                    } else if ("40".equals(statusCode)) {
                        throw GlobalException.build("个人H5开户失败！");
                    }
                } else {
                    throw GlobalException.build(object.getString("message"));
                }
            } else {
                throw GlobalException.build("请求个人H5开户失败");
            }
        } catch (Exception e) {
            throw GlobalException.build("个人H5开户失败");
        }
    }

    /**
     * 用户绑定支付标识
     *
     * @param map
     */
    private void applyBindAcct(Map<String, Object> map) {
        String result;
        try {
            result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_APPLY_BIND_ACCT, JSON.toJSONString(map), WcPayConstant.JSON);
        } catch (Exception e) {
            throw GlobalException.build("用户绑定支付标识失败");
        }
        if (null != result) {
            JSONObject object = JSONObject.parseObject(result);
            if (("200").equals(object.getString("code"))) {
                String statusCode = object.getJSONObject("data").getString("status");
                if ("20".equals(statusCode)) {
                    throw GlobalException.build("用户绑定支付标识处理中");
                } else if ("40".equals(statusCode)) {
                    throw GlobalException.build("用户绑定支付标识失败！");
                }
            } else {
                throw GlobalException.build(object.getString("message"));
            }
        } else {
            throw GlobalException.build("请求用户绑定支付标识失败");
        }

    }
}
